﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    [TestFixture]
    public class TestUIProp
    {

        [TestFixtureSetUp]
        public void SetupFixture()
        {
            TestUtilsDomain.SetupFixture();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            //-------------------------------------------------------------------------------------
            // You can choose here whether to run against a database or whether to use an in-memory
            // database for all the tests, which runs quickly. It doesn't however check that
            // your database has the correct structure, which is partly the purpose of these tests.
            // The generated tests do already use an in-memory database where possible.
            // In your custom tests, you can set them to use an in-memory database by copying the
            // line to the first line of your test.
            //-------------------------------------------------------------------------------------
            //BORegistry.DataAccessor = new DataAccessorDB();
            BORegistry.DataAccessor = new DataAccessorInMemory();
            TestUtilsDomain.SetupTest();
        }

        [Test]  // Checks that a related collection loads correctly (no tampering with class defs)
        public void Test_LoadThroughMultipleRelationship_UIParameters()
        {
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            UIField uIField = TestUtilsUIField.CreateSavedUIField();

            UIParameter boForRelationshipUIParameters = TestUtilsUIParameter.CreateUnsavedValidUIParameter();
            boForRelationshipUIParameters.UIPropID = uIField.UIPropID;
            boForRelationshipUIParameters.Save();

            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsDomain.WaitForGC();
            //---------------Assert Preconditions---------------
            Assert.AreEqual(1, uIField.UIParameters.Count);
            //---------------Execute Test ----------------------
            UIParameter loadedRelatedBO = Broker.GetBusinessObject<UIParameter>(boForRelationshipUIParameters.ID);
            UIField loadedUIField = Broker.GetBusinessObject<UIField>(uIField.ID);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, loadedUIField.UIParameters.Count);
            Assert.AreEqual(boForRelationshipUIParameters, loadedUIField.UIParameters[0]);
            Assert.AreEqual(loadedRelatedBO, loadedUIField.UIParameters[0]);
            Assert.AreEqual(loadedRelatedBO, uIField.UIParameters[0]);
        }
        [Test]  // Checks that deleting a parent deletes the child
        public void Test_MultipleRelationshipDeletion_DeleteRelated_UIParameters()
        {
            //---------------Set up test pack-------------------
            UIField uIField = TestUtilsUIField.CreateSavedUIField();

            UIParameter boForRelationshipUIParameters = TestUtilsUIParameter.CreateUnsavedValidUIParameter();
            boForRelationshipUIParameters.UIPropID = uIField.UIPropID;
            boForRelationshipUIParameters.Save();

            //---------------Assert Preconditions---------------
            Assert.AreEqual(1, uIField.UIParameters.Count);
            IRelationshipDef relationshipDef = ClassDef.Get<UIProp>().RelationshipDefCol["UIParameters"];
            Assert.AreEqual(DeleteParentAction.DeleteRelated, relationshipDef.DeleteParentAction);
            //---------------Execute Test ----------------------
            uIField.MarkForDelete();
            uIField.Save();
            //---------------Execute Test ----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsDomain.WaitForGC();

            try
            {
                Broker.GetBusinessObject<UIField>(uIField.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                Assert.IsTrue(ex.Message.Contains("There are no records in the database for the Class: UIField"));
            }

            try
            {
                Broker.GetBusinessObject<UIParameter>(boForRelationshipUIParameters.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                Assert.IsTrue(ex.Message.Contains("There are no records in the database for the Class: UIParameter"));
            }
        }

        [Test] // Checks that BOs in a single relationship load correctly (no tampering with class defs)
        public void Test_LoadThroughSingleRelationship_Property()
        {
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            UIProp uiProp = TestUtilsUIProp.CreateSavedUIProp();

            DMProperty boForRelatedProp = TestUtilsDMProperty.CreateSavedDMProperty();
            uiProp.Property = boForRelatedProp;
            uiProp.Save();

            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsDomain.WaitForGC();
            //---------------Execute Test ----------------------
            DMProperty loadedRelatedBO = Broker.GetBusinessObject<DMProperty>(boForRelatedProp.ID);
            UIProp returnedUIProp = Broker.GetBusinessObject<UIProp>(uiProp.ID);
            //---------------Test Result -----------------------
            Assert.AreEqual(boForRelatedProp, returnedUIProp.Property);
            Assert.AreEqual(loadedRelatedBO, returnedUIProp.Property);
            Assert.AreEqual(loadedRelatedBO, returnedUIProp.Property);
        }
    }
}
